package com.xz.simplerpc.rpc.protocol;

import com.xz.simplerpc.extension.URL;
import com.xz.simplerpc.rpc.api.*;
import com.xz.simplerpc.rpc.proxy.JdkProxyFactory;
import com.xz.simplerpc.rpc.rest.RestServer;
import org.jboss.resteasy.client.jaxrs.ResteasyClient;
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget;
import org.jboss.resteasy.core.ThreadLocalResteasyProviderFactory;
import org.jboss.resteasy.util.GetRestful;

import javax.ws.rs.client.WebTarget;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by fingal on 2018/1/6.
 */
public class RestProtocol implements Protocol {
    private JdkProxyFactory jdkProxyFactory = new JdkProxyFactory();
    private static RestServer server = null;

    private static Map<String, RestServer> servers = new ConcurrentHashMap<String, RestServer>();

    @Override
    public int getDefaultPort() {
        return 0;
    }

    @Override
    public <T> Exporter<T> export(Invoker<T> invoker, URL url) throws RpcException {
        String address = url.getIp() + ":" + url.getPort();
        T impl = jdkProxyFactory.getProxy(invoker, new Class[]{invoker.getInterface()});
        Class implClass = ServiceClassHolder.getInstance().popServiceClass();
        if(servers.get(address) == null) {
            server = new RestServer();
            server.start(url);
            servers.put(address, server);
        }
        final Class resourceDef = GetRestful.getRootResourceClass(implClass) != null ? implClass : invoker.getInterface();

        server.deploy(resourceDef, impl, null);
        return null;
    }

    @Override
    public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {

        ResteasyClient client = new ResteasyClientBuilder().build();
        //使用ThreadLocalResteasyProviderFactory直接指明builder是resteasy，防止与cxf冲突
        WebTarget target = client.target(ThreadLocalResteasyProviderFactory.getInstance().createUriBuilder().uri(refUrl(url)));

        ResteasyWebTarget rtarget = (ResteasyWebTarget)target;

        T imp = rtarget.proxy(type);

        return jdkProxyFactory.getInvoker(imp, type, url);
    }

    private String refUrl(URL url) {
        return "http://"+url.getAddress();
    }

    @Override
    public void destroy() {

    }
}
